package com.senriot.quickup.service

import com.querydsl.jpa.impl.JPAQueryFactory
import com.senriot.cloud.common.result.R
import com.senriot.cloud.common.result.fail
import com.senriot.cloud.common.result.success
import com.senriot.quickup.domain.*
import com.senriot.quickup.domain.enums.DevStatus
import com.senriot.quickup.repository.*
import com.senriot.quickup.security.WX_USER_PASSWORD
import com.senriot.quickup.service.dto.DeviceDTO
import com.senriot.quickup.service.dto.UserDTO
import com.senriot.quickup.service.mapper.DeviceMapper
import com.senriot.quickup.service.mapper.UserMapper
import me.chanjar.weixin.mp.api.WxMpService
import org.slf4j.LoggerFactory
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.time.Instant
import java.time.LocalDate
import java.util.*
import javax.persistence.EntityManager
import javax.transaction.Transactional


@Service
@Transactional
class WxService(
        private val userRepository: UserRepository,
        private val cityRepository: CityRepository,
        private val passwordEncoder: PasswordEncoder,
        private val wxMpService: WxMpService,
        private val wxUserInfoRepository: WxUserInfoRepository,
        private val orderRepository: OrderRepository,
        private val deviceRepository: DeviceRepository,
        private val userMapper: UserMapper,
        private val queryFactory: JPAQueryFactory,
        private val deviceMapper: DeviceMapper
)
{

    private val log = LoggerFactory.getLogger(this.javaClass)

    fun resellerSignup(dto: UserDTO): R<Void>
    {
        try
        {
            if (userRepository.exists(QUser.user.login.eq(dto.phone)))
                return fail("手机号已经注册")
            if (userRepository.exists(QUser.user.unionId.eq(dto.unionId)))
                return fail("您已经注册")
            val result = Address()
            cityRepository.findOne(QCity.city.areaCode.eq(dto.cityId.toString())).map {
                result.district = it
                result.city = cityRepository.findOne(QCity.city.id.eq(it.parentId)).get()
                result.province = cityRepository.findOne(QCity.city.id.eq(result.city?.parentId)).get()
                result
            }
            dto.authorities = listOf(102)
            dto.provinceId = result.province?.id
            dto.cityId = result.city?.id
            dto.districtId = result.district?.id
            wxUserInfoRepository.findOne(QWxUserInfo.wxUserInfo.id.eq(dto.unionId)).ifPresent {
                val user = userMapper.toEntity(dto).apply {
                    login = dto.phone
                    nickName = it.userInfo?.nickname
                    imageUrl = it.userInfo?.headImgUrl
                    sex = it.userInfo?.sex?.toInt()
                    password = passwordEncoder.encode(WX_USER_PASSWORD)
                    openId = it.token?.openId
                }
                userRepository.saveAndFlush(user)
            }
            return success()
        } catch (e: Exception)
        {
            e.printStackTrace()
            return fail("系统错误，请稍后再试")
        }

    }

    fun checkReseller(openId: String): R<Int>
    {
        val u = userRepository.findOne(QUser.user.unionId.equalsIgnoreCase(openId))
        return when
        {
            u.isPresent -> success(u.get().status)
            else        -> fail("用户不存在，可以注册")
        }
    }

    fun getWxOpenId(code: String, pay: Boolean): WxUserInfo
    {
        val userInfo = WxUserInfo()
        log.debug("${wxMpService.wxMpConfigStorage}")
        userInfo.token = wxMpService.oauth2getAccessToken(code)
        userInfo.id = userInfo.token?.unionId
        if (!pay)
        {
            userInfo.userInfo = wxMpService.oauth2getUserInfo(userInfo.token,"zh_CN")
            log.debug("userInfo ${userInfo.userInfo}")
        }
        userInfo.id?.let { wxUserInfoRepository.save(userInfo) }

        return userInfo
    }

    private fun getDayDate(): Instant?
    {
        val calendar = Calendar.getInstance()
        calendar.time = Date()
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        return calendar.time.toInstant()
    }
}
